package license

import (
	"context"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"

	"github.com/beherochuling/beesoft_api/app/dao"
	"github.com/beherochuling/beesoft_api/app/helper/net"
	"github.com/beherochuling/beesoft_api/app/model"
	"github.com/beherochuling/beesoft_api/app/model/entity"
	vipModel "github.com/beherochuling/beesoft_api/app/model/vip"
)

var License = licenseService{}

type licenseService struct{}

func (r *licenseService) Activate(ctx context.Context, req *vipModel.LicenseActivateRequest) net.ErrorCode {
	// 验证 1
	// 必须是用户或设备激活
	if req.UserId == 0 && req.DeviceId == 0 {
		return vipModel.ErrorCodeInvalidParams
	}

	// 激活码
	codeService := NewLicenseCode()
	code := codeService.ShowCode(ctx, req.Code)
	if code == nil {
		return vipModel.ErrorCodeLicenseNotFound
	}

	// 批次
	batch := codeService.ShowBatch(ctx, code.LicenseId)
	if batch == nil || batch.Status != vipModel.StatusTypeNormal {
		return vipModel.ErrorCodeLicenseStatusNotOK
	}

	// 验证
	check := 0
	if code.CountActived >= code.CountAllowed {
		return vipModel.ErrorCodeLicenseLimitReached

		check = 1
	}
	if batch.IsActivity == vipModel.FlagTrue {
		now := gtime.Now()
		if !batch.ValidFrom.IsZero() && batch.ValidFrom.After(now) {
			return vipModel.ErrorCodeLicenseInvalidTime
		}
		if !batch.ValidTo.IsZero() && batch.ValidTo.Before(now) {
			return vipModel.ErrorCodeLicenseInvalidTime
		}

		check = 2
	}

	//authInfo := req.ToAccountV2()
	if check != 0 {
		//logWhere := g.Map{
		//	dao.Logs.Columns().RelationType: authInfo.RelationType,
		//	dao.Logs.Columns().RelationId:   authInfo.RelationId,
		//	dao.Logs.Columns().CodeId:       code.Id,
		//}
		//if req.ProductId == model.ProductIdGemSoft {
		//	logWhere[dao.Logs.Columns().ProductId] = req.ProductId
		//}
		//
		//logService := NewLog()
		//// if code.ProductId == model.ProductIdRecCloudWeb && code.Type == model.VipTypeCandy {
		//// 	logService.SetTableType(model.LogTableCandy)
		//// }
		//log := logService.
		//	SetProductId(req.ProductId).
		//	Scan(ctx, logWhere)
		//if log != nil {
		//	if req.ActivateType == model.CodeActivateTypeVip {
		//		return model.SuccessCode
		//	}
		//
		//	return model.ErrorCodeCodeHasActived
		//} else if check == 1 { // log == nil
		//	return model.ErrorCodeCodeHasActived
		//}
		//
		//// 活动激活码，验证活动 id, transaction_id 字段记录
		//transactionId, err := strconv.Atoi(batch.TransactionId)
		//if err == nil && transactionId != 0 {
		//	log = logService.Scan(ctx, g.Map{
		//		dao.Logs.Columns().RelationType:                  authInfo.RelationType,
		//		dao.Logs.Columns().RelationId:                    authInfo.RelationId,
		//		fmt.Sprintf("%s != ", dao.Logs.Columns().CodeId): 0,
		//		dao.Logs.Columns().TransactionId:                 transactionId,
		//	})
		//	if log != nil {
		//		return model.ErrorCodeCodeHasActivedActivity
		//	}
		//}
	}

	// 更新激活码
	codeService.UpdateCode(ctx, code.Id, g.Map{
		dao.VipLicenseCodes.Columns().CountActived: &gdb.Counter{
			Field: dao.VipLicenseCodes.Columns().CountActived,
			Value: 1,
		},
	})

	// 权益
	rights := codeService.ShowRights(ctx, code.LicenseId)
	if len(rights) > 0 {
		for _, _ = range rights {
			//licenseType := model.LicenseType(right.LicenseType)
			//periodType := model.PeriodType(right.PeriodType)
			//
			//data := g.Map{
			//	dao.Users.Columns().LicenseType: &licenseType,
			//	dao.Users.Columns().MaxDevices:  right.MaxDevices,
			//}
			//// 以下两种：取消 period_type 对记录的影响，特别是 lifetime 时，可能将记录变成终身用户了
			//if right.VipType != model.VipTypeQuota && right.VipType != model.VipTypeCoin {
			//	data[dao.Users.Columns().PeriodType] = &periodType
			//}
			//
			//switch right.VipType {
			//case vipModel.VipTypePeriod:
			//	data[model.FieldPeriod] = &Period{
			//		Amount: int(right.VipQuantity),
			//		Type:   model.PeriodType(right.PeriodType),
			//	}
			//case vipModel.VipTypeQuota:
			//	data[dao.Users.Columns().Quota] = right.Quota * right.VipQuantity
			//case vipModel.VipTypeCandy:
			//	data[dao.Users.Columns().Quota] = right.Quota
			//	data[model.FieldPeriod] = &Period{
			//		Amount: int(right.VipQuantity),
			//		Type:   model.PeriodType(right.PeriodType),
			//	}
			//default:
			//}

			//NewVipFactory().
			//	SetProductId(right.RelationId).
			//	SetVipType(right.VipType).
			//	SetLogType(model.LogTypeCode).
			//	SetRelation(authInfo).
			//	SetLicenseType(right.LicenseType).
			//	SetPeriodType(right.PeriodType).
			//	SetMaxDevices(right.MaxDevices).
			//	SetCodeId(code.Id).
			//	SetTransactionId(batch.TransactionId).
			//	NewVip().
			//	Modify(ctx, g.Map{}, data)
		}
	}

	return model.SuccessCode
}

// Generate 生成激活码
// 1. 后台生成
// 2. 支付生成
// 3. 活动生成
// 4. 三方激活码转换
func (r *licenseService) Generate(ctx context.Context, req *vipModel.LicenseGenerateRequest) (uint, net.ErrorCode) {
	if req.CountAllowed == 0 {
		req.CountAllowed = 1
	}
	// 1. 生成批次
	lastInsertId, err := dao.VipLicenses.Ctx(ctx).
		InsertAndGetId(entity.VipLicenses{
			IsActivity:    req.IsActivity,
			ValidFrom:     gtime.New(req.ValidFrom),
			ValidTo:       gtime.New(req.ValidTo),
			Quantity:      req.Amount, // todo 字段不对应
			Channel:       req.Channel,
			Function:      req.Function,
			TransactionId: req.TransactionId,
			Remark:        req.Remark,
			Status:        vipModel.StatusTypeNormal,
			CreatedBy:     req.CreatedBy,
		})
	if err != nil {
		panic(err)
	}
	if lastInsertId <= 0 {
		panic(err)
	}
	licenseId := uint(lastInsertId)

	// 2. 存储权益
	var rights []entity.VipLicenseRights
	for _, item := range req.Rights {
		vipQuantity := item.VipQuantity
		if item.VipType == vipModel.VipTypePeriod && item.Quantity != 0 {
			vipQuantity = item.Quantity
		}

		rights = append(rights, entity.VipLicenseRights{
			LicenseId:    licenseId,
			RelationType: item.RelationType,
			RelationId:   item.RelationId,
			VipType:      item.VipType,
			Quota:        item.Quota,
			LicenseType:  item.LicenseType,
			PeriodType:   item.PeriodType,
			MaxDevices:   item.MaxDevices,
			VipQuantity:  vipQuantity,
		})
	}

	if len(rights) > 0 {
		_, err = dao.VipLicenseRights.Ctx(ctx).
			Insert(rights)
		if err != nil {
			panic(err)
		}
	}

	// 3. 生成存储激活码
	var codes []entity.VipLicenseCodes
	for i := 0; i < int(req.Amount); i++ {
		code := r.GenerateCode(req.IsNumber)
		codes = append(codes, entity.VipLicenseCodes{
			LicenseId:    licenseId,
			Code:         code,
			CountAllowed: req.CountAllowed,
			CountActived: 0,
		})
	}

	if len(codes) > 0 {
		_, err = dao.VipLicenseCodes.Ctx(ctx).
			Insert(codes)
		if err != nil {
			panic(err)
		}
	}

	return licenseId, model.SuccessCode
}
func (r *licenseService) DestroyCodesBatch(ctx context.Context, req *vipModel.LicenseCodeDestroyBatchRequest) {
	m := dao.VipLicenseCodes.Ctx(ctx).
		// Where(dao.LicenseCodes.Columns().Status, model.StatusTypeNormal). // 可用的
		WhereIn(dao.VipLicenseCodes.Columns().Code, req.Codes)

	var items []entity.VipLicenseCodes
	err := m.Scan(&items)
	if err != nil {
		panic(err)
	}

	for _, item := range items {
		r.Reset(ctx, &item)
	}

	data := g.Map{}
	switch req.Type {
	case vipModel.LicenseCodeActionReset: // 重置即恢复初始，同时回收之前权益
		data[dao.VipLicenseCodes.Columns().CountActived] = 0
	case vipModel.LicenseCodeActionRevoke: // 吊销即删除，同时回收之前的权益
		data[dao.VipLicenseCodes.Columns().DeletedAt] = gtime.Now()
	}

	_, err = m.Update(data)
	if err != nil {
		panic(err)
	}
}
func (r *licenseService) Reset(ctx context.Context, code *entity.VipLicenseCodes) {
	rights := NewLicenseCode().ShowRights(ctx, code.LicenseId)
	for _, right := range rights {
		//switch right.RelationType {
		//case model.CodeRelationTypeProduct:
		r.ResetProductRight(ctx, code.Id, right)
		//default:
		//	glog.Warningf(ctx, "code relationType %d not supported", right.RelationType)
		//}
	}
}
func (r *licenseService) ResetProductRight(ctx context.Context, codeId uint, right entity.VipLicenseRights) {
	//if right.VipType == model.VipTypeCandy {
	//	product := Product.Get(ctx, right.RelationId)
	//	if product.Config.CandyType == model.CandyTypeReccloud {
	//		_, err := dao.LogsCandy.Ctx(ctx).
	//			Where(dao.LogsCandy.Columns().CodeId, codeId).
	//			Where(dao.LogsCandy.Columns().Type, model.LogTypeCode).
	//			Delete()
	//		if err != nil {
	//			panic(err)
	//		}
	//
	//		return
	//	}
	//}
	//
	//remark := "\nRevoked"
	//
	//m := NewLog().Table(ctx).
	//	Where(dao.Logs.Columns().CodeId, codeId).
	//	Where(dao.Logs.Columns().Type, model.LogTypeCode). // 激活日志
	//	WhereNotLike(dao.Logs.Columns().Remark, fmt.Sprintf("%%%s%%", remark)).
	//	Where(dao.Logs.Columns().ProductId, right.RelationId).
	//	Where(dao.Logs.Columns().VipType, right.VipType)
	//
	//var logs []entity.Logs
	//err := m.Scan(&logs)
	//if err != nil {
	//	panic(err)
	//}
	//
	//_, err = m.Update(g.Map{
	//	dao.Logs.Columns().Remark: gdb.Raw(fmt.Sprintf("concat(`%s`, \"%s\")", dao.Logs.Columns().Remark, remark)),
	//})
	//if err != nil {
	//	panic(err)
	//}
	//
	//for _, log := range logs {
	//	data := g.Map{}
	//
	//	switch right.VipType {
	//	case vipModel.VipTypePeriod:
	//		data[model.FieldPeriod] = &Period{
	//			Amount:  int(right.VipQuantity),
	//			Type:    model.PeriodType(right.PeriodType),
	//			Reverse: true,
	//		}
	//	case vipModel.VipTypeQuota:
	//		data[dao.Users.Columns().Quota] = -right.Quota * right.VipQuantity
	//	case vipModel.VipTypeCandy:
	//		data[dao.Users.Columns().Quota] = -right.Quota * right.VipQuantity
	//		data[model.FieldPeriod] = &Period{
	//			Type:    model.PeriodType(right.PeriodType),
	//			Reverse: true,
	//		}
	//	case vipModel.VipTypeDefault:
	//		data[dao.Users.Columns().Quota] = -right.Quota
	//		data[model.FieldPeriod] = &Period{
	//			Amount:  int(right.VipQuantity),
	//			Type:    model.PeriodType(right.PeriodType),
	//			Reverse: true,
	//		}
	//	default:
	//	}

	//NewVipFactory().
	//	SetVipType(right.VipType).
	//	SetLogType(model.LogTypeCodeRevoke).
	//	SetRelation(&model.AccountV2{
	//		RelationType: log.RelationType,
	//		RelationId:   log.RelationId,
	//	}).
	//	SetProductId(right.RelationId).
	//	SetLicenseType(right.LicenseType).
	//	SetPeriodType(right.PeriodType).
	//	SetMaxDevices(right.MaxDevices).
	//	SetCodeId(codeId).
	//	SetTransactionId(log.TransactionId). // 保留原日志的订单号
	//	NewVip().
	//	Modify(ctx, g.Map{}, data)
}

// 内部

func (r *licenseService) GenerateCode(isNumber uint) string { // todo 排重
	generator := NewCodeGenerator()

	if isNumber != 0 {
		generator = generator.SetNumber()
	}

	return generator.Generate()
}
